<template>
  <div class="tech-docs-container">
    <!-- 左侧文档目录 -->
    <div class="docs-sidebar">
      <div class="sidebar-header">
        <el-input
          v-model="searchQuery"
          placeholder="搜索文档..."
          prefix-icon="Search"
          clearable
          size="small"
        />
      </div>
      <div class="doc-tree">
        <el-tree
          :data="docTree"
          :props="defaultProps"
          @node-click="handleNodeClick"
          :default-expanded-keys="['1']"
        />
      </div>
      <!-- 在线用户列表 -->
      <div class="online-users-section">
        <div class="section-title">在线用户</div>
        <div class="users-list">
          <div v-for="user in userList" :key="user" class="user-item">
            {{ users[user]?.name || user }}
          </div>
        </div>
      </div>
    </div>

    <!-- 右侧内容区 -->
    <div class="docs-content relative">
      <!-- 文档内容区 -->
      <div class="content-container">
     

        <!-- 主要内容区 -->
        <div class="main-content">
          <div v-if="!isChat" class="doc-content" v-html="currentDocContent"></div>
          <div v-else class="chat-content">
            <!-- 置顶消息显示区域 -->
            <div v-if="pinnedMessages.length > 0" class="pinned-messages-container">
              <div class="pin-header">
                <div class="pin-title">
                  <i class="el-icon-pin"></i>
                  <span>置顶消息 ({{ pinnedMessages.length }})</span>
                </div>
                <!-- 为土豆添加隐藏/显示按钮 -->
                <el-button 
                  type="text"
                  size="small"
                  @click="togglePinnedMessages"
                  class="toggle-pinned-button"
                >
                  {{ showPinnedMessages ? '隐藏置顶' : '显示置顶' }}
                </el-button>
              </div>
              <!-- 根据显示状态控制置顶消息列表的显示 -->
              <div v-show="showPinnedMessages || currentUser?.name !== '土豆'" class="pinned-messages-list">
                <div v-for="msg in pinnedMessages" :key="msg.messageId" class="pinned-message">
                  <div class="pin-content">
                    <span class="pin-name">{{ msg.message.sender }}:</span>
                    <template v-if="msg.image">
                      <img 
                        :src="msg.image" 
                        class="pin-image"
                        :alt="msg.content"
                      />
                    </template>
                    <template v-else>
                      <span v-html="formatMessageContent(msg.message.content)"></span>
                    </template>
                  </div>
                  <!-- 只有"什么时候当老板"能看到取消置顶按钮 -->
                  <el-button 
                    v-if="currentUser?.name === '什么时候当老板'"
                    type="text" 
                    size="small" 
                    @click="handleUnpin(msg)"
                    class="unpin-button"
                  >
                    取消置顶
                  </el-button>
                </div>
              </div>
            </div>

            <!-- 消息列表 -->
            <div class="messages" ref="messagesList">
              <div v-for="msg in messages" :key="msg.id" :class="['message', msg.type]">
                <div class="message-header">
                  <span class="message-name">{{ msg.name }}</span>
                  <div class="message-actions">
                    <!-- 只有"什么时候当老板"能看到置顶按钮 -->
                    <el-button 
                      v-if="currentUser?.name === '什么时候当老板'"
                      type="text" 
                      size="small" 
                      @click="handlePin(msg)"
                      class="pin-button"
                    >
                      {{ pinnedMessages.some(p => p.messageId === msg.id.toString()) ? '取消置顶' : '置顶' }}
                    </el-button>
                    <el-button 
                      type="text" 
                      size="small" 
                      @click="handleQuote(msg)"
                      class="quote-button"
                    >
                      引用
                    </el-button>
                  </div>
                </div>
                <div class="message-content">
                  <div v-if="msg.quote" class="quoted-message">
                    <div class="quoted-header">
                      <span class="quoted-name">{{ msg.quote.name }}</span>
                      <span class="quoted-time">{{ msg.quote.time }}</span>
                    </div>
                    <div class="quoted-content">
                      <template v-if="msg.quote.image">
                        <img 
                          :src="msg.quote.image" 
                          class="quoted-image"
                          :alt="msg.quote.content"
                        />
                      </template>
                      <template v-else>
                        <div v-html="formatMessageContent(msg.quote.content)" class="message-text"></div>
                      </template>
                    </div>
                  </div>
                  <template v-if="msg.image">
                    <div v-if="currentUser?.name === '土豆'" class="image-hidden">
                      <div class="image-placeholder">
                        [图片已隐藏]
                        <el-button type="text" @click="handleImagePreview(msg.image)">
                          点击查看
                        </el-button>
                      </div>
                    </div>
                    <img 
                      v-else
                      :src="msg.image" 
                      :alt="msg.content"
                      @load="handleImageLoad"
                      :class="{ gif: msg.isGif }"
                      @click="!msg.isGif && handleImagePreview(msg.image)"
                      :style="!msg.isGif ? 'cursor: zoom-in' : ''"
                    />
                  </template>
                  <template v-else>
                    <div 
                      v-html="formatMessageContent(msg.content)" 
                      class="message-text"
                      :class="{
                        'shake-text': isShaking,
                        'highlight-keywords': showKeywordColors
                      }"
                    ></div>
                  </template>
                </div>
                <div class="message-time">{{ msg.time }}</div>
              </div>
            </div>
          </div>

          <!-- 底部评论区 -->
          <div class="comment-section">
            <div class="comment-header">
              <div class="header-left">
                <span>评论</span>
                <el-tag v-if="currentUser&&currentUser?.name !== '土豆' " size="small" style="margin-left: 8px">
                  {{ currentUser.name }}
                </el-tag>
              </div>
              <div class="header-right">
                <el-button type="text" @click="clearMessages">
                  清空记录
                </el-button>
                <el-button v-if="!currentUser" type="text" @click="showLoginDialog = true">
                  登录
                </el-button>
                <template v-else>
                  <el-button type="text" @click="toggleMode">
                    切换模式
                  </el-button>
                  <el-button type="text" @click="handleLogout">
                    退出
                  </el-button>
                </template>
              </div>
            </div>
            <div class="comment-input">
              <div v-if="quoteMessage" class="quoting-message">
                <span class="quoting-content">
                  回复 {{ quoteMessage.name }}: {{ quoteMessage.content }}
                </span>
                <span class="cancel-quote" @click="quoteMessage = null">
                  ✕
                </span>
              </div>
              <!-- 表情选择器 -->
              <div class="emoji-picker" v-if="showEmoji">
                <div class="emoji-tabs">
                  <div 
                    class="tab-item" 
                    :class="{ active: currentTab === 'emoji' }"
                    @click="currentTab = 'emoji'"
                  >
                    表情
                  </div>
                  <div 
                    class="tab-item" 
                    :class="{ active: currentTab === 'gif' }"
                    @click="currentTab = 'gif'"
                  >
                    动图
                  </div>
                </div>
                <div class="emoji-container">
                  <template v-if="currentTab === 'emoji'">
                    <span 
                      v-for="emoji in emojiList" 
                      :key="emoji"
                      class="emoji-item"
                      @click="insertEmoji(emoji)"
                    >
                      {{ emoji }}
                    </span>
                  </template>
                  <template v-else>
                    <div 
                      v-for="gif in gifEmojis" 
                      :key="gif.url"
                      class="gif-item"
                      @click="sendGif(gif)"
                    >
                      <img :src="gif.url" :alt="gif.name">
                    </div>
                  </template>
                </div>
              </div>
              <el-input
                v-model="messageInput"
                type="textarea"
                :rows="3"
                :placeholder="isChat ? '发送消息...' : '添加评论...'"
                @keydown.enter.prevent="handleEnterPress"
              />
              <div class="input-actions">
                <el-button-group>
                  <el-button icon="Sunny" plain size="small" @click="showEmoji = !showEmoji">表情</el-button>
                  <el-button 
                    icon="Magic-stick" 
                    plain 
                    size="small" 
                    @click="toggleKeywordColors"
                    :class="{ 'is-active': showKeywordColors }"
                  >
                    高亮
                  </el-button>
                  <el-button icon="Document" plain size="small">插入代码</el-button>
                  <el-upload
                    class="upload-button"
                    :show-file-list="false"
                    :before-upload="handleImageUpload"
                    accept="image/*"
                  >
                    <el-button icon="Picture" plain size="small">插入图片</el-button>
                  </el-upload>
                </el-button-group>
                <el-button 
                  type="primary" 
                  size="small" 
                  @click="sendMessage" 
                  v-if="currentUser && currentUser.name !== '小红'"
                >
                  {{ isChat ? '发送' : '评论' }}    
                </el-button>
              </div>
            </div>
          </div>
        </div>
      </div>

      <div class="absolute right-[1vw] top-[10vh] " v-if="currentUser&&currentUser?.name == '土豆' ">
        <img src="./img/gg.png" alt="" class="w-[10.6vw] h-[30vh]">
      </div>
    </div>

    <!-- 登录对话框 -->
    <el-dialog
      v-model="showLoginDialog"
      title="登录"
      width="400px"
      :close-on-click-modal="false"
    >
      <el-form :model="loginForm" label-width="80px">
        <el-form-item label="用户名">
          <el-input v-model="loginForm.username" />
        </el-form-item>
        <el-form-item label="密码">
          <el-input v-model="loginForm.password" type="password" />
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="showLoginDialog = false">取消</el-button>
        <el-button type="primary" @click="handleLogin">登录</el-button>
      </template>
    </el-dialog>

    <!-- 图片预览对话框 -->
    <el-dialog
      v-model="showImageViewer"
      title="图片预览"
      width="80%"
    >
      <el-image
        :src="previewImage"
        :preview-src-list="[previewImage]"
        fit="contain"
        @close="closePreview"
      ></el-image>
    </el-dialog>

    <!-- 添加图片预览组件 -->
    <el-image-viewer
      v-if="showImageViewer"
      :url-list="[previewImage]"
      @close="closePreview"
    />
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted, computed, onUnmounted, nextTick } from 'vue'
import MarkdownIt from 'markdown-it'
import { ElMessage } from 'element-plus'

const md = new MarkdownIt()
const searchQuery = ref('')
const messageInput = ref('')
const selectedVersion = ref('2.0.0')

// 添加状态控制
const isChat = ref(false)
const currentDocId = ref('js-basics')
const userList = ref<string[]>([])

// 添加用户相关的类型和状态
interface User {
  id: string
  name: string
  password: string
}

const users = {
  user1: { id: 'user1', name: '土豆', password: 'pass1' },
  user2: { id: 'user2', name: 'charmingCat', password: 'pass2' },
  user3: { id: 'user3', name: '什么时候当老板', password: 'pass3' },
  user4: { id: 'user4', name: '小宇', password: 'pass4' },
  user5: { id: 'user5', name: '小红', password: 'pass5' },
  user6: { id: 'user6', name: '小李', password: 'pass6' },
  user7: { id: 'user7', name: '小张', password: 'pass7' },
  user8: { id: 'user8', name: '表弟', password: 'pass8' },
  user9: { id: 'user9', name: '小赵', password: 'pass9' },
  user10: { id: 'user10', name: '小孙', password: 'pass10' },
  
}

// 添加存储相关的常量和函数
const STORAGE_KEY = 'chat_user'

// 从本地存储加载用户信息
const loadUserFromStorage = (): User | null => {
  const stored = localStorage.getItem(STORAGE_KEY)
  return stored ? JSON.parse(stored) : null
}

// 保存用户信息到本地存储
const saveUserToStorage = (user: User | null) => {
  if (user) {
    localStorage.setItem(STORAGE_KEY, JSON.stringify(user))
  } else {
    localStorage.removeItem(STORAGE_KEY)
  }
}

// 修改用户状态的初始值，从本地存储加载
const currentUser = ref<User | null>(loadUserFromStorage())

const showLoginDialog = ref(false)
const loginForm = ref({
  username: '',
  password: ''
})

// 修改消息接口
interface Message {
  id: number
  content: string
  type: 'sent' | 'received'
  time: string
  name?: string
  image?: string
  isGif?: boolean
  quote?: {
    id: number
    content: string
    name: string
    time: string
    image?: string
  }
  isPinned?: boolean
}

// 修改消息数组的类型
const messages = ref<Message[]>([
  {
    id: 1,
    content: '这篇文档写得很好，特别是关于异步编程的部分',
    type: 'received',
    time: '10:30',
    name: 'Alice'
  },
  {
    id: 2,
    content: '确实，Promise和async/await的例子很清晰',
    type: 'received',
    time: '10:31',
    name: 'Bob'
  }
])

const currentDoc = ref({ title: 'JavaScript 高级开发指南' })

// 将文档内容定义为单独的常量
const JS_BASICS_CONTENT = '# JavaScript 基础教程\n\n' +
  '## 1. 变量和数据类型\n\n' +
  'JavaScript 是一种动态类型语言，使用 `var`、`let` 和 `const` 来声明变量。\n\n' +
  '### 1.1 变量声明\n\n' +
  '```javascript\n' +
  '// 使用 let 声明变量（推荐）\n' +
  'let message = "Hello World";\n\n' +
  '// 使用 const 声明常量\n' +
  'const PI = 3.14159;\n' +
  '```\n\n' +
  '### 1.2 数据类型\n\n' +
  '- Number：数字类型\n' +
  '- String：字符串类型\n' +
  '- Boolean：布尔类型\n' +
  '- null：空值\n' +
  '- undefined：未定义\n';

const VUE_BEST_PRACTICES_CONTENT = '# Vue.js 最佳实践指南\n\n' +
  '## 1. 组件设计原则\n\n' +
  '### 1.1 单一职责\n\n' +
  '每个组件应该只做一件事，这样可以保持组件的简单性和可维护性。\n\n' +
  '### 1.2 组件通信\n\n' +
  '```vue\n' +
  '<!-- 父组件 -->\n' +
  '<template>\n' +
  '  <child-component :data="data" @update="handleUpdate" />\n' +
  '</template>\n' +
  '```\n\n' +
  '## 2. 性能优化\n\n' +
  '### 2.1 计算属性\n\n' +
  '```javascript\n' +
  'export default {\n' +
  '  computed: {\n' +
  '    fullName() {\n' +
  '      return this.firstName + " " + this.lastName;\n' +
  '    }\n' +
  '  }\n' +
  '}\n' +
  '```';

// 先定义 docTree
const docTree = ref([
  {
    label: '开发文档',
    children: [
      { label: 'JavaScript 基础教程', id: 'js-basics' },
      { label: 'Vue.js 最佳实践', id: 'vue-best-practices' },
      { label: 'React 性能优化', id: 'react-perf' },
      { label: 'TypeScript 入门指南', id: 'ts-guide' }
    ]
  },
  {
    label: '项目规范',
    children: [
      { label: '代码规范', id: 'code-standards' },
      { label: 'Git 工作流', id: 'git-workflow' },
      { label: '代码审查指南', id: 'code-review' }
    ]
  },
  {
    label: '架构设计',
    children: [
      { label: '系统架构概览', id: 'sys-arch' },
      { label: '微服务设计模式', id: 'microservice' },
      { label: '数据库设计规范', id: 'db-design' }
    ]
  },
  {
    label: '更新日志',
    children: [
      {
        label: '2025-02-27',
        id: 'changelog-20250227',
        content: `# 更新日志 2025-02-27

## 新增功能
1. 置顶消息功能
   - 为用户添加了隐藏/显示置顶消息的按钮
   - 添加了平滑的折叠/展开动画效果
   - 保持了原有的置顶消息功能
   - 状态会在会话期间保持 
   `
      },
    { 
        label: '2025-02-26', 
        id: 'changelog-20250226',
        content: `# 更新日志 2025-02-26

## 新增功能
1. 假广告功能
   - 针对土豆用户可以显示假广告
2. 关键词高亮功能
   - 点击高亮按钮可以高亮关键词
`
    },
    { 
        label: '2025-02-25', 
        id: 'changelog-20250225',
        content: `# 更新日志 2025-02-25

## 新增功能
1. 图片预览功能
   - 点击图片可以全屏预览
   - 支持图片缩放和关闭
   - 优化了图片显示效果

2. 消息自动滚动
   - 发送新消息后自动滚动到最新位置
   - 添加平滑滚动效果
   - 优化了滚动体验

3. 用户界面优化
   - 隐藏土豆用户的用户标签
   - 优化了图片加载和显示效果
   - 改进了消息列表的滚动行为

## 修复问题
1. 修复了消息发送后不能自动滚动到底部的问题
2. 优化了图片加载完成后的滚动处理
3. 改进了消息容器的高度计算方式

## 技术改进
1. 添加了延迟滚动机制，确保内容完全加载
2. 优化了图片预览组件的层级显示
3. 改进了消息列表的性能表现`
      },
      { 
        label: '2025-02-24', 
        id: 'changelog-20250224',
        content: `# 更新日志 2025-02-24

## 新增功能
1. 表情包系统
   - 支持发送静态表情
   - 支持发送 GIF 动图
   - 添加表情选择器

2. 在线用户列表
   - 显示当前在线用户
   - 实时更新用户状态
   - 优化用户显示效果

## 系统优化
1. 改进了 WebSocket 连接的稳定性
2. 优化了消息发送和接收机制
3. 改进了用户登录体验`
      }
    ]
  }
])

// 然后定义 docContents
const docContents: Record<string, { title: string; content: string }> = {
  'js-basics': {
    title: 'JavaScript 基础教程',
    content: JS_BASICS_CONTENT
  },
  'vue-best-practices': {
    title: 'Vue.js 最佳实践指南',
    content: VUE_BEST_PRACTICES_CONTENT
  }
}

// 添加更新日志内容
const updateLogNodes = docTree.value[3].children as Array<{ id: string; label: string; content: string }>
updateLogNodes.forEach(node => {
  docContents[node.id] = {
    title: node.label,
    content: node.content
  }
})

// 修改渲染方式，添加类型断言
const currentDocContent = computed(() => {
  const doc = docContents[currentDocId.value] || docContents['js-basics']
  return md.render(doc.content)
})

const defaultProps = {
  children: 'children',
  label: 'label'
}

const handleNodeClick = (data: any) => {
  currentDoc.value.title = data.label
  // 根据节点的 id 设置文档内容
  if (data.id) {
    currentDocId.value = data.id
  } else {
    // 根据标题设置对应的文档ID（保持原有逻辑向后兼容）
    if (data.label === 'JavaScript 基础教程') {
      currentDocId.value = 'js-basics'
    } else if (data.label === 'Vue.js 最佳实践') {
      currentDocId.value = 'vue-best-practices'
    }
  }
  isChat.value = false // 切换文档时显示文档内容
}

// 修改关键词匹配规则
const keywordPatterns = {
  // 情感表达
  positive: /(真棒|太好了|完美|漂亮|优秀|厉害|可以的|不错|好评|赞|支持)/,
  negative: /(糟糕|遗憾|可惜|难受|不行|差评|退步|失望)/,
  
  // 时间相关
  deadline: /(紧急|截止|尽快|马上|立即|火急|抓紧)/,
  schedule: /下周|本周|明天|今天|下个月|待会|等会|稍后|很快|即将/,
  
  // 技术相关
  frontend: /(vue|react|angular|webpack|vite|typescript|javascript|html|css|sass|less)/i,
  backend: /(node|python|java|golang|php|mysql|redis|mongodb|nginx|docker)/i,
  
  // 状态标记
  status: /(完成|进行中|待处理|已解决|未解决|待确认|已确认|通过|驳回)/,
  priority: /(高优先级|中优先级|低优先级|p0|p1|p2)/i,
  
  // 互动用语
  question: /(请问|疑问|怎么办|如何|为什么|能否|是否|能不能|有没有)/,
  action: /(建议|推荐|希望|要求|需要|计划|打算|准备)/
}

// 修改消息格式化方法，添加空值检查
const formatMessageContent = (content: string | undefined) => {
  if (!content) return '' // 如果内容为空，返回空字符串
  
  let formattedContent = content

  try {
    // 股票相关
    formattedContent = formattedContent.replace(
      /\b(s[hz]\d{6}|[036]\d{5})\b/gi,
      (match) => `<span class="stock-code-keyword">${match}</span>`
    )
    formattedContent = formattedContent.replace(
      /(买入|加仓|建仓|看多|多头|突破|反弹)/g,
      (match) => `<span class="stock-buy-keyword">${match}</span>`
    )
    formattedContent = formattedContent.replace(
      /(卖出|减仓|清仓|看空|空头|跌破|回调|割肉|止损|亏钱|亏麻了|跌破)/g,
      (match) => `<span class="stock-sell-keyword">${match}</span>`
    )
    formattedContent = formattedContent.replace(
      /(\d+(\.\d{1,2})?元|￥\d+(\.\d{1,2})?|\d+(\.\d{1,2})?美元|\$\d+(\.\d{1,2})?)/g,
      (match) => `<span class="price-keyword">${match}</span>`
    )

    // 处理情感表达
    formattedContent = formattedContent.replace(
      /(真棒|太好了|完美|漂亮|优秀|厉害|可以的|不错|好评|赞|支持|牛逼|666|很好|盈利|赚钱)/g,
      (match) => `<span class="positive-keyword">${match}</span>`
    )
    formattedContent = formattedContent.replace(
      /(糟糕|遗憾|可惜|难受|不行|差评|退步|失望|boss|唉|犹豫|亏钱|亏麻了)/g,
      (match) => `<span class="negative-keyword">${match}</span>`
    )

    // 处理时间相关
    formattedContent = formattedContent.replace(
      /(紧急|截止|尽快|马上|立即|火急|抓紧)/g,
      (match) => `<span class="deadline-keyword">${match}</span>`
    )
    formattedContent = formattedContent.replace(
      /下周|本周|明天|今天|下个月|待会|等会|稍后|很快|即将|以后/g,
      (match) => `<span class="schedule-keyword">${match}</span>`
    )

    // 处理技术相关
    formattedContent = formattedContent.replace(
      /(vue|react|angular|webpack|vite|typescript|javascript|html|css|sass|less)/gi,
      (match) => `<span class="frontend-keyword">${match}</span>`
    )
    formattedContent = formattedContent.replace(
      /(node|python|java|golang|php|mysql|redis|mongodb|nginx|docker)/gi,
      (match) => `<span class="backend-keyword">${match}</span>`
    )

    // 处理状态标记
    formattedContent = formattedContent.replace(
      /(完成|进行中|待处理|已解决|未解决|待确认|已确认|通过|驳回)/g,
      (match) => `<span class="status-keyword">${match}</span>`
    )
    formattedContent = formattedContent.replace(
      /(机会|中优先级|低优先级|p0|p1|p2)/gi,
      (match) => `<span class="priority-keyword">${match}</span>`
    )

    // 处理互动用语
    formattedContent = formattedContent.replace(
      /(请问|疑问|怎么办|如何|为什么|能否|是否|能不能|有没有)/g,
      (match) => `<span class="question-keyword">${match}</span>`
    )
    formattedContent = formattedContent.replace(
      /(建议|推荐|希望|要求|需要|计划|打算|准备|追涨|追高|抄底|低吸|杀跌|回调|学学|学习|赚钱)/g,
      (match) => `<span class="action-keyword">${match}</span>`
    )

    return formattedContent
  } catch (error) {
    console.error('格式化消息内容出错:', error)
    return content // 如果处理出错，返回原始内容
  }
}

// 修改 WebSocket 连接逻辑
const ws = ref<WebSocket | null>(null)

// 添加在线用户列表状态
const onlineUsers = ref<User[]>([])

const connectWebSocket = () => {
  if (!currentUser.value) return
  
  console.log('正在连接WebSocket...')
  ws.value = new WebSocket('ws://cylyxsz.w1.luyouxia.net')
  
  ws.value.onopen = () => {
    console.log('WebSocket连接成功')
    
    // 发送登录信息
    if (currentUser.value && ws.value) {
      const loginMessage = {
        type: 'login',
        username: currentUser.value.id,
        password: users[currentUser.value.id as keyof typeof users]?.password || ''
      }
      console.log('发送登录信息:', loginMessage)
      ws.value.send(JSON.stringify(loginMessage))
    }

    // 设置消息处理函数
    if (ws.value) {
      ws.value.onmessage = (event: MessageEvent) => {
        const data = JSON.parse(event.data)
        console.log('收到消息:', data)

        switch (data.type) {
          case 'message':
          case 'gif':
          case 'image':
            // 处理新消息提醒
            handleNewMessage(data)
            
            // 现有的消息处理逻辑...
            const senderId = data.sender || data.username
            if (senderId === currentUser.value?.id) return
            
            const messageSender = users[senderId as keyof typeof users]
            const senderName = messageSender?.name || '未知用户'
            
            messages.value.push({
              id: Date.now(),
              content: data.type === 'gif' ? data.name : data.content,
              type: 'received',
              time: new Date().toLocaleTimeString(),
              name: senderName,
              image: data.type === 'gif' ? data.url : undefined,
              isGif: data.type === 'gif'
            })
            scrollToBottom()
            break
            
          case 'error':
            ElMessage.error(data.message)
            break
            
          case 'userList':
            userList.value = data.users
            break

          // ... 其他消息类型处理 ...
        }
      }
    }
  }
  
  ws.value.onerror = (error) => {
    console.error('WebSocket错误:', error)
    ElMessage.error('连接出错')
  }
  
  ws.value.onclose = () => {
    console.log('WebSocket连接关闭')
    if (currentUser.value) {
      setTimeout(connectWebSocket, 3000)
    }
  }
}

// 处理回车按键
const handleEnterPress = (e: KeyboardEvent) => {
  // 如果按住了 Shift 键，就是换行
  if (e.shiftKey) {
    return
  }
  // 否则发送消息
  sendMessage()
}

// 添加技术助手的回复内容
const techExplanations = [
  {
    content: '这个问题涉及到前端性能优化的核心概念。建议从以下几个方面着手：1. 资源加载优化 2. 代码执行优化 3. 渲染性能优化。具体可以使用懒加载、缓存策略、代码分割等技术。'
  },
  {
    content: '在前端工程化方面，推荐使用现代化的构建工具如Vite、Webpack等，配合ESLint、Prettier进行代码规范化，使用TypeScript增强代码的可维护性。CI/CD流程也是不可或缺的一环。'
  },
  {
    content: '说到前端框架选择，需要根据具体项目需求来决定。Vue适合中小型项目，上手快速；React生态更丰富，适合大型应用；Angular则更适合企业级应用。每个框架都有其优势。'
  },
  {
    content: '关于状态管理，小型项目可以使用Vue的Composition API或React的Context；中大型项目建议使用Vuex/Pinia或Redux/MobX，它们提供了更完善的状态管理方案。'
  },
  {
    content: '前端安全是个重要话题。常见的安全问题包括XSS、CSRF、SQL注入等。建议使用CSP、HTTPS、输入验证等多重防护手段，同时保持依赖包的及时更新。'
  },
  {
    content: '说到浏览器渲染原理，关键是理解CRP(关键渲染路径)。包括DOM树和CSSOM树的构建、布局、绘制等步骤。这对性能优化很有帮助。'
  },
  {
    content: '前端测试是保证代码质量的重要手段。单元测试可以用Jest，E2E测试推荐Cypress，组件测试可以用Testing Library。要建立完整的测试体系。'
  },
  {
    content: '前端部署现在推荐使用容器化方案，比如Docker。配合CI/CD工具如Jenkins、GitLab CI，可以实现自动化部署。静态资源最好使用CDN加速。'
  },
  {
    content: '前端模块化设计很重要。可以使用ES6模块系统，结合设计模式如单例、观察者、工厂等。合理的模块拆分可以提高代码复用性和可维护性。'
  },
  {
    content: '前端调试技巧：善用Chrome DevTools，掌握断点调试、性能分析、内存泄漏检测等功能。对于复杂问题，console的各种方法都很有用。'
  }
]

// 添加 messagesList ref
const messagesList = ref<HTMLElement | null>(null)

// 修改 scrollToBottom 方法，添加延迟以确保 DOM 更新完成
const scrollToBottom = () => {
  nextTick(() => {
    setTimeout(() => {
      if (messagesList.value) {
        messagesList.value.scrollTop = messagesList.value.scrollHeight
      }
    }, 100) // 添加小延迟确保内容渲染完成
  })
}

// 添加引用消息的状态
const quoteMessage = ref<Message | null>(null)

// 添加处理引用的方法
const handleQuote = (msg: Message) => {
  quoteMessage.value = msg
  // 聚焦输入框
  nextTick(() => {
    const textarea = document.querySelector('.comment-input textarea') as HTMLTextAreaElement
    if (textarea) {
      textarea.focus()
    }
  })
}

// 修改发送消息的方法
const sendMessage = () => {
  if (!messageInput.value.trim() || !currentUser?.value || !ws.value) {
    if (!currentUser.value) {
      ElMessage.warning('请先登录')
      showLoginDialog.value = true
    }
    return
  }
  
  const currentTime = new Date().toLocaleTimeString()
  const messageContent = messageInput.value.trim()
  
  try {
    const message = {
      type: 'message',
      content: messageContent,
      username: currentUser.value.id,
      // 添加引用消息
      quote: quoteMessage.value ? {
        id: quoteMessage.value.id,
        content: quoteMessage.value.content,
        name: quoteMessage.value.name || '',
        time: quoteMessage.value.time,
        image: quoteMessage.value.image
      } : null
    }
    
    ws.value.send(JSON.stringify(message))
    
    messages.value.push({
      id: Date.now(),
      content: messageContent,
      type: 'received',
      time: currentTime,
      name: currentUser.value.name,
      quote: quoteMessage.value ? {
        id: quoteMessage.value.id,
        content: quoteMessage.value.content,
        name: quoteMessage.value.name || '',
        time: quoteMessage.value.time,
        image: quoteMessage.value.image
      } : undefined
    })
    
    // 如果是土豆发送的消息，添加技术助手的回复
    if (currentUser.value.name === '土豆') {
      // 从技术讲解内容中随机选择一个
      const randomIndex = Math.floor(Math.random() * techExplanations.length)
      const techResponse = techExplanations[randomIndex]
      
      setTimeout(() => {
        messages.value.push({
          id: Date.now(),
          content: techResponse.content,
          type: 'received',
          time: new Date().toLocaleTimeString(),
          name: '技术助手'
        })
        scrollToBottom()
      }, 1000) // 1秒后回复
    }
    
    messageInput.value = ''
    quoteMessage.value = null // 清除引用
    scrollToBottom()
    
  } catch (error) {
    console.error('发送消息失败:', error)
    ElMessage.error('发送消息失败')
  }
}

// 清除聊天记录
const clearMessages = () => {
    messages.value = []
}

// 添加切换模式的快捷键处理
const toggleMode = () => {
  isChat.value = !isChat.value
}

// 修改登录函数
const handleLogin = () => {
  const user = users[loginForm.value.username as keyof typeof users]
  if (user && user.password === loginForm.value.password) {
    currentUser.value = {
      id: user.id,
      name: user.name
    }
    // 保存到本地存储
    saveUserToStorage(currentUser.value)
    showLoginDialog.value = false
    
    // 连接 WebSocket
    connectWebSocket()
  } else {
    ElMessage.error('用户名或密码错误')
  }
}

// 添加登出函数
const handleLogout = () => {
  currentUser.value = null
  saveUserToStorage(null)
  if (ws.value) {
    ws.value.close()
    ws.value = null
  }
}

// 在组件卸载时关闭连接
onUnmounted(() => {
  if (ws.value) {
    ws.value.close()
    ws.value = null
  }
})

onMounted(() => {
  // 如果有保存的用户信息，自动连接WebSocket
  if (currentUser.value) {
    connectWebSocket()
  }

  // 添加快捷键监听
  window.addEventListener('keydown', (e) => {
    if (e.ctrlKey && e.altKey && e.key === 't') {
      toggleMode()
    }
  })

  // 点击其他地方关闭表情选择器
  document.addEventListener('click', (e: MouseEvent) => {
    const target = e.target as HTMLElement
    if (!target.closest('.emoji-picker') && !target.closest('.el-button')) {
      showEmoji.value = false
    }
  })

  // 添加页面可见性监听
  document.addEventListener('visibilitychange', handleVisibilityChange)
})

// 添加表情相关的状态
const showEmoji = ref(false)
const emojiList = [
  '😀', '😃', '😄', '😁', '😆', '😅', '😂', '🤣',
  '😊', '😇', '🙂', '🙃', '😉', '😌', '😍', '🥰',
  '😘', '😗', '😙', '😚', '😋', '😛', '😝', '😜',
  '🤪', '🤨', '🧐', '🤓', '😎', '🤩', '🥳', '😏',
  '😒', '😞', '😔', '😟', '😕', '🙁', '☹️', '😣',
  '😖', '😫', '😩', '🥺', '😢', '😭', '😤', '😠',
  '😡', '🤬', '🤯', '😳', '🥵', '🥶', '😱', '😨'
]

// 插入表情的方法
const insertEmoji = (emoji: string) => {
  messageInput.value += emoji
  showEmoji.value = false  // 选择后关闭表情选择器
}

// 添加动态表情包数组
const gifEmojis = [
  {
    name: '大笑',
    url: 'https://media.giphy.com/media/v1.Y2lkPTc5MGI3NjExcW1meWM2MzF1ZXJ1d2R6Y2dlMTlwbTk4NnBxaGx6ZDV1bXF1aHR6eCZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9cw/10JhviFuU2gWD6/giphy.gif'
  },
  {
    name: '性感',
    url: 'https://img.soogif.com/l9GTE7tT7f54boLnNOpgMt646DSORiji.gif'
  },
  {
    name: '熊猫当眼睛',
    url: 'https://img.soogif.com/kyUlnVmF3WPWszuwWR3ZxXxxqhNUZ9Bv.gif'
  },
  {
    name: '在线偷听',
    url: 'https://img.soogif.com/KHbGIl4vd0xzEEnTYmOKoJ83ULzp4hoU.gif_s400x0'
  },
  {
    name: '舔狗',
    url: 'https://n.sinaimg.cn/sinakd20122/524/w262h262/20250206/191f-gif544af907967993ac316e32d710bdd1b7.gif'
  },
  {
    name: '我来了',
    url: 'https://tukuimg.bdstatic.com/scrop/cf6afe45b4ad2e02e884f239451858cd.gif'
  },
  {
    name: '一脚踩死你',
    url: 'https://img.soogif.com/a9AH5yU2FQG0FNMw8CK0fctcJ1Arj0BR.gif'
  }
]

// 添加标签页状态
const currentTab = ref('emoji')

// 修改发送 GIF 的方法
const sendGif = (gif: { name: string, url: string }) => {
  if (!ws.value || !currentUser.value) return
  
  try {
    // 发送 GIF 消息
    const message = {
      type: 'gif',
      name: gif.name,
      url: gif.url,
      sender: currentUser.value.id,
      timestamp: new Date().toISOString()
    }
    
    ws.value.send(JSON.stringify(message))
    
    // 本地显示自己发送的 GIF
    messages.value.push({
      id: Date.now(),
      content: gif.name,
      type: 'received',
      time: new Date().toLocaleTimeString(),
      name: currentUser.value.name,
      image: gif.url,
      isGif: true
    })
  } catch (error) {
    console.error('发送GIF失败:', error)
    ElMessage.error('发送GIF失败')
  }
  
  showEmoji.value = false
}

// 图片上传相关
const MAX_IMAGE_SIZE = 5 * 1024 * 1024 // 5MB

// 处理图片上传
const handleImageUpload = async (file: File) => {
  console.log('开始处理图片:', file.type, file.size)

  if (!ws.value || !currentUser.value) {
    ElMessage.warning('请先登录')
    showLoginDialog.value = true
    return false
  }

  // 检查文件类型
  if (!file.type.startsWith('image/')) {
    ElMessage.error('请选择图片文件')
    return false
  }

  // 检查文件大小
  if (file.size > MAX_IMAGE_SIZE) {
    ElMessage.error('图片大小不能超过5MB')
    return false
  }

  try {
    // 使用 Promise 包装 FileReader
    const base64 = await new Promise<string>((resolve, reject) => {
      const reader = new FileReader()
      reader.onload = (e) => {
        const result = e.target?.result
        console.log('FileReader 结果类型:', typeof result)
        console.log('FileReader 结果前缀:', result?.toString().substring(0, 50))
        
        if (result && typeof result === 'string') {
          // 确保数据是完整的 base64 格式
          if (result.startsWith('data:image/')) {
            resolve(result)
          } else {
            console.error('无效的图片格式:', result.substring(0, 50))
            reject(new Error('Invalid image format'))
          }
        } else {
          console.error('读取结果无效:', result)
          reject(new Error('Failed to read file'))
        }
      }
      reader.onerror = () => reject(reader.error)
      reader.readAsDataURL(file)
    })

    const message = {
      type: 'image',
      image: base64,
      sender: currentUser.value.id,
      timestamp: new Date().toISOString(),
      name: currentUser.value.name
    }

    ws.value.send(JSON.stringify(message))

    // 本地显示自己发送的图片
    messages.value.push({
      id: Date.now(),
      content: '[图片]',
      type: 'received',
      time: new Date().toLocaleTimeString(),
      name: currentUser.value.name,
      image: base64,
      isGif: false
    })

  } catch (error) {
    console.error('处理图片失败:', error)
    if (error instanceof Error) {
      console.error('错误详情:', error.message)
      console.error('错误堆栈:', error.stack)
    }
    ElMessage.error('图片处理失败')
    return false
  }

  return false // 阻止自动上传
}

// 添加监听图片加载完成的方法
const handleImageLoad = () => {
  scrollToBottom()
}

// 在 script setup 中添加预览相关的状态
const showImageViewer = ref(false)
const previewImage = ref('')

// 添加图片预览处理方法
const handleImagePreview = (imageUrl: string) => {
  previewImage.value = imageUrl
  showImageViewer.value = true
}

// 添加关闭预览的方法
const closePreview = () => {
  showImageViewer.value = false
  previewImage.value = ''
}

// 添加抖动状态控制
const isShaking = ref(false)

// 添加切换抖动的方法
const toggleShaking = () => {
  isShaking.value = !isShaking.value
}

// 添加关键词高亮状态控制
const showKeywordColors = ref(true)

// 添加切换关键词高亮的方法
const toggleKeywordColors = () => {
  showKeywordColors.value = !showKeywordColors.value
}

// 修改置顶消息相关的状态和类型
interface PinnedMessage extends Message {
  messageId: string
  sender: string
  timestamp: string
}

const pinnedMessages = ref<PinnedMessage[]>([]) // 改为数组存储多条置顶消息

// 修改置顶/取消置顶的方法
const handlePin = (msg: Message) => {
  if (!currentUser.value || currentUser.value.name !== '什么时候当老板') return
  
  const isPinned = pinnedMessages.value.some(p => p.messageId === msg.id.toString())
  
  ws.value?.send(JSON.stringify({
    type: isPinned ? 'unpinMessage' : 'pinMessage',
    messageId: msg.id.toString(),
    message: {
      messageId: msg.id.toString(),
      sender: msg.name || currentUser.value.name,
      content: msg.content,
      timestamp: msg.time,
      image: msg.image
    }
  }))
}

// 添加取消置顶的方法
const handleUnpin = (msg: PinnedMessage) => {
  if (!currentUser.value || currentUser.value.name !== '什么时候当老板') return
  
  ws.value?.send(JSON.stringify({
    type: 'unpinMessage',
    messageId: msg.messageId
  }))
}

// 添加置顶消息显示控制
const showPinnedMessages = ref(true)

// 添加切换置顶消息显示的方法
const togglePinnedMessages = () => {
  showPinnedMessages.value = !showPinnedMessages.value
}

// 添加页面可见性和消息提醒相关的状态
const isPageVisible = ref(true)
const unreadCount = ref(0)
const originalTitle = document.title

// 在 WebSocket 消息处理中添加提醒逻辑
const handleNewMessage = (data: any) => {
  // 如果页面不可见，更新未读消息计数和标题
  if (!isPageVisible.value) {
    unreadCount.value++
    document.title = `(${unreadCount.value}条新消息) ${originalTitle}`
  }
}

// 添加页面可见性变化处理
const handleVisibilityChange = () => {
  isPageVisible.value = document.visibilityState === 'visible'
  if (isPageVisible.value) {
    // 页面重新可见时，重置未读消息计数和标题
    unreadCount.value = 0
    document.title = originalTitle
  }
}

// 在组件挂载时添加页面可见性监听
onMounted(() => {
  // 添加页面可见性监听
  document.addEventListener('visibilitychange', handleVisibilityChange)
  
  // 现有的挂载逻辑...
})

// 在组件卸载时清理
onUnmounted(() => {
  // 移除页面可见性监听
  document.removeEventListener('visibilitychange', handleVisibilityChange)
  // 恢复原始标题
  document.title = originalTitle
})
</script>

<style scoped>
.tech-docs-container {
  display: flex;
  height: 100vh;
  background: #ffffff;
}

.docs-sidebar {
  width: 280px;
  border-right: 1px solid #e4e4e4;
  background: #f8f8f8;
  display: flex;
  flex-direction: column;
}

.sidebar-header {
  padding: 16px;
  border-bottom: 1px solid #e4e4e4;
}

.doc-tree {
  flex: 1;
  padding: 16px;
  overflow-y: auto;
}

.docs-content {
  flex: 1;
  overflow: hidden;
}

.content-container {
  display: flex;
  height: 100%;
  position: relative;
}

.content-nav {
  width: 200px;
  padding: 24px 0;
  border-left: 1px solid #e4e4e4;
  background: #ffffff;
  position: sticky;
  top: 0;
  height: 100vh;
}

.nav-title {
  padding: 0 24px;
  font-size: 14px;
  font-weight: 500;
  color: #1a1a1a;
  margin-bottom: 8px;
}

.nav-items {
  padding: 0 16px;
}

.nav-item {
  display: block;
  padding: 4px 8px;
  color: #666;
  font-size: 13px;
  text-decoration: none;
  border-radius: 4px;
  margin: 4px 0;
}

.nav-item:hover {
  color: #3eaf7c;
  background: #f1f1f1;
}

.main-content {
  flex: 1;
  display: flex;
  flex-direction: column;
  padding: 40px;
  overflow-y: auto;
}

.doc-content {
  max-width: none;
  padding-right: 24px;
  font-size: 15px;
  line-height: 1.6;
  color: #2c3e50;
}

.doc-content :deep(h1) {
  font-size: 2em;
  font-weight: 600;
  border-bottom: 1px solid #eaecef;
  padding-bottom: 0.3em;
  margin: 1em 0 16px;
}

.doc-content :deep(h2) {
  font-size: 1.5em;
  font-weight: 600;
  padding-bottom: 0.3em;
  border-bottom: 1px solid #eaecef;
  margin: 1em 0 16px;
}

.doc-content :deep(h3) {
  font-size: 1.25em;
  font-weight: 600;
  margin: 1em 0 16px;
}

.doc-content :deep(p) {
  margin: 1em 0;
  line-height: 1.7;
}

.doc-content :deep(ul),
.doc-content :deep(ol) {
  padding-left: 2em;
  margin: 1em 0;
}

.doc-content :deep(li) {
  margin: 0.5em 0;
}

.doc-content :deep(code) {
  background-color: #f6f8fa;
  padding: 0.2em 0.4em;
  border-radius: 3px;
  font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace;
  font-size: 0.9em;
}

.doc-content :deep(pre) {
  background: #282c34;
  color: #abb2bf;
  padding: 16px;
  border-radius: 6px;
  overflow: auto;
  margin: 1em 0;
}

.doc-content :deep(pre code) {
  background: transparent;
  padding: 0;
  color: inherit;
  font-size: 0.9em;
  line-height: 1.5;
}

.doc-content :deep(blockquote) {
  margin: 1em 0;
  padding: 0 1em;
  color: #6a737d;
  border-left: 0.25em solid #dfe2e5;
}

.doc-content :deep(table) {
  border-collapse: collapse;
  width: 100%;
  margin: 1em 0;
}

.doc-content :deep(th),
.doc-content :deep(td) {
  padding: 6px 13px;
  border: 1px solid #dfe2e5;
}

.doc-content :deep(th) {
  background-color: #f6f8fa;
  font-weight: 600;
}

.doc-content :deep(tr:nth-child(2n)) {
  background-color: #f6f8fa;
}

.doc-content :deep(img) {
  max-width: 100%;
  margin: 1em 0;
  border-radius: 4px;
}

.doc-content :deep(hr) {
  height: 1px;
  background-color: #e1e4e8;
  border: none;
  margin: 24px 0;
}

/* 代码高亮主题 */
.doc-content :deep(pre code) {
  /* JavaScript */
  .keyword { color: #c678dd; }
  .string { color: #98c379; }
  .comment { color: #5c6370; font-style: italic; }
  .number { color: #d19a66; }
  .function { color: #61afef; }
  .operator { color: #56b6c2; }
  
  /* HTML/Vue */
  .tag { color: #e06c75; }
  .attr-name { color: #d19a66; }
  .attr-value { color: #98c379; }
}

/* 移动端适配 */
@media screen and (max-width: 768px) {
  .doc-content {
    padding: 16px;
    font-size: 14px;
  }

  .doc-content :deep(h1) {
    font-size: 1.8em;
  }

  .doc-content :deep(h2) {
    font-size: 1.4em;
  }

  .doc-content :deep(h3) {
    font-size: 1.2em;
  }

  .doc-content :deep(pre) {
    padding: 12px;
    font-size: 13px;
  }
}

.comment-section {
  position: sticky;
  bottom: 0;
  background: #fff;
  padding: 20px 0;
  border-top: 1px solid #e4e4e4;
  margin-top: auto;
  z-index: 10;
  box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.05);
}

.comment-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 16px;
}

.comment-input {
  background: #fff;
  position: relative;
}

.input-actions {
  display: flex;
  justify-content: space-between;
  margin-top: 8px;
}

/* 聊天相关样式 */
.chat-content {
  padding: 16px;
  flex: 1;
  overflow-y: auto;
}

.messages {
  flex: 1;
  overflow-y: auto;
  padding: 20px;
  height: calc(100vh - 300px); /* 设置固定高度，减去其他元素的高度 */
  scroll-behavior: smooth; /* 添加平滑滚动效果 */
}

.message {
  margin-bottom: 16px;
  max-width: 80%;
}

.message.sent {
  margin-left: auto;
}

.message.received {
  margin-right: auto;
}

.message-content {
  background: #f9f9f9;
  padding: 12px;
  border-radius: 4px;
  font-size: .8vw;
  color: #666;
}

.message.sent .message-content {
  background: #f0f7ff;
  color: #555;
}

.message-time {
  font-size: 12px;
  color: #999;
  margin-top: 4px;
}

:deep(.el-tree-node__content) {
  height: 32px;
}

:deep(.el-tree) {
  background: transparent;
}

/* 添加新的样式 */
.message-header {
  font-size: 12px;
  color: #666;
  margin-bottom: 4px;
}

.message-name {
  font-weight: 500;
}

/* 在线用户列表样式 */
.online-users-section {
  padding: 16px;
  border-top: 1px solid #e4e4e4;
  background: #fff;
}

.section-title {
  font-size: 14px;
  font-weight: 500;
  color: #333;
  margin-bottom: 12px;
}

.users-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.user-item {
  font-size: 13px;
  color: #666;
  padding: 6px 8px;
  border-radius: 4px;
  background: #f5f7fa;
  transition: all 0.3s ease;
}

.user-item:hover {
  background: #ecf5ff;
  color: #409eff;
}

/* 添加表情选择器样式 */
.emoji-picker {
  position: absolute;
  bottom: 100%;
  left: 0;
  background: white;
  border: 1px solid #e4e4e4;
  border-radius: 4px;
  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
  z-index: 1000;
  margin-bottom: 8px;
}

.emoji-tabs {
  display: flex;
  border-bottom: 1px solid #e4e4e4;
}

.tab-item {
  padding: 8px 16px;
  cursor: pointer;
  font-size: 14px;
  color: #666;
}

.tab-item.active {
  color: #409eff;
  border-bottom: 2px solid #409eff;
}

.emoji-container {
  display: grid;
  grid-template-columns: repeat(8, 1fr);
  gap: 4px;
  padding: 8px;
  max-height: 200px;
  overflow-y: auto;
}

.emoji-item {
  cursor: pointer;
  font-size: 20px;
  padding: 4px;
  text-align: center;
  transition: all 0.2s;
}

.emoji-item:hover {
  background: #f5f7fa;
  border-radius: 4px;
  transform: scale(1.2);
}

/* 添加 GIF 表情样式 */
.gif-item {
  cursor: pointer;
  padding: 4px;
  border-radius: 4px;
  transition: all 0.2s;
}

.gif-item:hover {
  background: #f5f7fa;
  transform: scale(1.05);
}

.gif-item img {
  width: 100px;
  height: 100px;
  object-fit: cover;
  border-radius: 4px;
}

/* 修改消息中 GIF 的样式 */
.message img.gif {
  width: 150px;
  height: 150px;
  object-fit: cover;
}

/* 技术助手消息样式 */
.message.received[data-sender="技术助手"] .message-content {
  background: #f5f5f5;
  border-left: 3px solid #42b983;
}

/* 修改图片消息样式 */
.message img {
  max-width: 100%;
  border-radius: 4px;
  display: block;
}

.message img.gif {
  max-width: 200px;
  max-height: 200px;
  object-fit: cover;
}

/* 添加GIF占位符样式 */
.gif-placeholder {
  padding: 8px;
  background: #f5f5f5;
  border-radius: 4px;
  color: #666;
  font-size: 12px;
}

/* 上传按钮样式 */
.upload-button {
  display: inline-block;
}

/* 图片消息样式 */
.message img:not(.gif) {
  max-width: 300px;
  max-height: 300px;
  object-fit: contain;
  border-radius: 4px;
  cursor: pointer;
}

/* 添加图片预览相关样式 */
.message img:not(.gif) {
  max-width: 300px;
  max-height: 300px;
  object-fit: contain;
  border-radius: 4px;
  transition: transform 0.2s;
}

.message img:not(.gif):hover {
  transform: scale(1.02);
}

/* 自定义图片预览组件样式 */
:deep(.el-image-viewer__wrapper) {
  z-index: 2100;
}

:deep(.el-image-viewer__close) {
  color: #fff;
}

/* 添加隐藏图片的占位符样式 */
.image-hidden {
  padding: 12px;
  background: #f5f5f5;
  border-radius: 4px;
  margin: 8px 0;
}

.image-placeholder {
  color: #666;
  font-size: 14px;
  display: flex;
  align-items: center;
  gap: 8px;
}

.image-placeholder :deep(.el-button--text) {
  padding: 0;
  height: auto;
  font-size: 14px;
}

.image-placeholder :deep(.el-button--text) {
  padding: 0;
  height: auto;
  font-size: 14px;
}

/* 添加引用消息样式 */
.quoted-message {
  background: #f0f7ff;
  padding: 8px;
  border-radius: 4px;
  margin-bottom: 8px;
}

.quoted-header {
  font-size: 12px;
  color: #666;
  margin-bottom: 4px;
}

.quoted-name {
  font-weight: 500;
}

.quoted-time {
  font-size: 12px;
  color: #999;
}

.quoted-content {
  font-size: 14px;
  color: #666;
}

.quoted-image {
  max-width: 100%;
  border-radius: 4px;
  margin-top: 8px;
}

/* 添加引用提示样式 */
.quoting-message {
  background: #f0f7ff;
  padding: 8px;
  border-radius: 4px;
  margin-bottom: 8px;
}

.quoting-content {
  font-size: 14px;
  color: #666;
}

.cancel-quote {
  cursor: pointer;
  color: #999;
  margin-left: 8px;
}

/* 引用消息样式 */
.message-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.quote-button {
  opacity: 0;
  transition: opacity 0.2s;
}

.message:hover .quote-button {
  opacity: 1;
}

.quoted-message {
  background: rgba(0, 0, 0, 0.03);
  border-left: 3px solid #409eff;
  padding: 8px;
  margin-bottom: 8px;
}

.quoted-header {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 4px;
}

.quoted-name {
  font-size: 12px;
  color: #409eff;
  font-weight: 500;
}

.quoted-time {
  font-size: 12px;
  color: #999;
}

.quoted-content {
  font-size: 13px;
  color: #666;
}

.quoted-image {
  max-width: 150px;
  max-height: 150px;
  border-radius: 4px;
  margin-top: 4px;
}

/* 当前正在引用的消息提示 */
.quoting-message {
  background: #f5f7fa;
  padding: 8px 12px;
  border-radius: 4px;
  margin-bottom: 8px;
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.quoting-content {
  font-size: 13px;
  color: #666;
}

.cancel-quote {
  color: #999;
  cursor: pointer;
}

.cancel-quote:hover {
  color: #f56c6c;
}

/* 关键词样式基础版本（无颜色） */
.message-content :deep([class$="-keyword"]) {
  font-weight: 500;
  transition: all 0.3s ease;
}

/* 关键词样式高亮版本 */
.message-content .highlight-keywords :deep(.positive-keyword) {
  color: #52c41a;
}

.message-content .highlight-keywords :deep(.negative-keyword) {
  color: #ff4d4f;
}

.message-content .highlight-keywords :deep(.deadline-keyword) {
  color: #ff7a45;
  padding: 0 2px;
}

.message-content .highlight-keywords :deep(.schedule-keyword) {
  color: #40a9ff;
}

.message-content .highlight-keywords :deep(.frontend-keyword) {
  color: #13c2c2;
  background: rgba(19, 194, 194, 0.1);
  padding: 0 4px;
  border-radius: 2px;
}

.message-content .highlight-keywords :deep(.backend-keyword) {
  color: #722ed1;
  background: rgba(114, 46, 209, 0.1);
  padding: 0 4px;
  border-radius: 2px;
}

.message-content .highlight-keywords :deep(.status-keyword) {
  color: #2f54eb;
}

.message-content .highlight-keywords :deep(.priority-keyword) {
  color: #eb2f96;
}

.message-content .highlight-keywords :deep(.question-keyword) {
  color: #faad14;
}

.message-content .highlight-keywords :deep(.action-keyword) {
  color: #1890ff;
}

/* 悬停效果只在高亮模式下生效 */
.message-content .highlight-keywords :deep([class$="-keyword"]):hover {
  opacity: 0.8;
  cursor: pointer;
  text-decoration: underline;
}

/* 技术关键词的特殊效果只在高亮模式下生效 */
.message-content .highlight-keywords :deep(.frontend-keyword):hover,
.message-content .highlight-keywords :deep(.backend-keyword):hover {
  transform: translateY(-1px);
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}

/* 股票相关关键词样式 */
.message-content .highlight-keywords :deep(.stock-code-keyword) {
  color: #1890ff;
  font-weight: 500;
  padding: 0 2px;
  background: rgba(24, 144, 255, 0.1);
  border-radius: 2px;
}

.pinned-message :deep(.stock-code-keyword) {
  color: #1890ff;
  font-weight: 500;
  padding: 0 2px;
  background: rgba(24, 144, 255, 0.1);
  border-radius: 2px;
}

.message-content .highlight-keywords :deep(.stock-buy-keyword) {
  color: #f5222d;
  font-weight: 500;
  background: rgba(245, 34, 45, 0.1);
  padding: 0 2px;
  border-radius: 2px;
}

.pinned-message :deep(.stock-buy-keyword) {
  color: #f5222d;
  font-weight: 500;
  background: rgba(245, 34, 45, 0.1);
  padding: 0 2px;
  border-radius: 2px;
}

.message-content .highlight-keywords :deep(.stock-sell-keyword) {
  color: #52c41a;
  font-weight: 500;
  background: rgba(82, 196, 26, 0.1);
  padding: 0 2px;
  border-radius: 2px;
}

.pinned-message :deep(.stock-sell-keyword) {
  color: #52c41a;
  font-weight: 500;
  background: rgba(82, 196, 26, 0.1);
  padding: 0 2px;
  border-radius: 2px;
}

.message-content .highlight-keywords :deep(.price-keyword) {
  color: #722ed1;
  font-weight: 500;
  background: rgba(114, 46, 209, 0.1);
  padding: 0 2px;
  border-radius: 2px;
}

.pinned-message :deep(.price-keyword) {
 color: #722ed1;
  font-weight: 500;
  background: rgba(114, 46, 209, 0.1);
  padding: 0 2px;
  border-radius: 2px;
}


/* 置顶消息样式 */
.pinned-messages-container {
  position: sticky;
  top: 0;
  z-index: 10;
  background: #fff;
  border-bottom: 1px solid #ffe7ba;
  padding: 8px 0;
  margin-bottom: 16px;
}

.pinned-messages-list {
  max-height: 200px;
  overflow-y: auto;
  scrollbar-width: thin;
  scrollbar-color: #ffd591 #fff7e6;
}

.pinned-messages-list::-webkit-scrollbar {
  width: 6px;
}

.pinned-messages-list::-webkit-scrollbar-track {
  background: #fff7e6;
}

.pinned-messages-list::-webkit-scrollbar-thumb {
  background-color: #ffd591;
  border-radius: 3px;
}

.pinned-message {
  background: #fff7e6;
  border-radius: 4px;
  margin-bottom: 8px;
  padding: 12px;
  border: 1px solid #ffe7ba;
  position: relative;
}

.pin-header {
  display: flex;
  align-items: center;
  justify-content: space-between; /* 修改为两端对齐 */
  margin-bottom: 8px;
  padding: 0 12px;
}

.pin-title {
  display: flex;
  align-items: center;
  gap: 6px;
  color: #d46b08;
  font-size: 14px;
  font-weight: 500;
}

.pin-content {
  font-size: 14px;
  color: #666;
  padding-right: 40px;
}

.pin-name {
  color: #d46b08;
  font-weight: 500;
  margin-right: 8px;
}

.pin-image {
  max-width: 200px;
  max-height: 150px;
  border-radius: 4px;
  margin: 4px 0;
}

.unpin-button {
  position: absolute;
  right: 12px;
  top: 12px;
  color: #d46b08;
  font-size: 12px;
}

.unpin-button:hover {
  color: #ad5502;
}

/* 消息操作按钮样式 */
.message-actions {
  display: flex;
  gap: 8px;
  opacity: 0;
  transition: opacity 0.2s;
}

.message:hover .message-actions {
  opacity: 1;
}

.pin-button {
  color: #d46b08;
}

.pin-button:hover {
  color: #ad5502;
}

/* 为土豆添加隐藏/显示按钮 */
.toggle-pinned-button {
  color: #d46b08;
  font-size: 12px;
}

.toggle-pinned-button:hover {
  color: #ad5502;
}

/* 添加折叠/展开动画 */
.pinned-messages-list {
  transition: max-height 0.3s ease-in-out;
}

.pinned-messages-list[hidden] {
  max-height: 0;
  overflow: hidden;
  margin: 0;
  padding: 0;
}
</style> 
